Evaluating Parameter Interdependence

Test run on 10/29/15 by Ed Bokhour.

Using SD PCB Interface Board serial number 002, SD PCB Driver Board serial number 002, and SD PCB Video Board serial number 001. Running with new wrapper (FPE_Wrapper_6.1.2, for San Diego PCBs, dated 10/19/15.

Set up the FPE

Remember that whenever you power-cycle the Observatory Simulator, you should set preload=True below.

When you are running this notbook and it has not been power cycled, you should set preload=False.


In [ ]:
from tessfpe.dhu.fpe import FPE
from tessfpe.dhu.unit_tests import check_house_keeping_voltages
import time
fpe1 = FPE(1, debug=False, preload=False, FPE_Wrapper_version='6.1.2')
print fpe1.version
time.sleep(.01)
if check_house_keeping_voltages(fpe1):
    print "Wrapper load complete. Interface voltages OK."

Set the operating parameters to the default values:


In [ ]:
def set_fpe_defaults(fpe):
    "Set the FPE to the default operating parameters, and outputs a table of the default values"
    defaults = {}
    for k in range(len(fpe.ops.address)):
        if fpe.ops.address[k] is None:
            continue
        fpe.ops.address[k].value = fpe.ops.address[k].default
        defaults[fpe.ops.address[k].name] = fpe.ops.address[k].default
    return defaults

Get, sort, and print the default operating parameters:


In [ ]:
from tessfpe.data.operating_parameters import operating_parameters

In [ ]:
for k in sorted(operating_parameters.keys()):
    v = operating_parameters[k]
    print k, ":", v["default"], v["unit"]

Take a number of sets of housekeeping data, with one operating parameter varying across it's control range, then repeat for every operating parameter:


In [ ]:
def get_base_name(name):
    import re
    if '_offset' not in name:
        return None
    offset_name = name
    derived_parameter_name = name.replace('_offset', '')
    base_name = None
    if 'low' in derived_parameter_name:
        base_name = derived_parameter_name.replace('low', 'high')            
    if 'high' in derived_parameter_name:
        base_name = derived_parameter_name.replace('high', 'low')
    if 'output_drain' in derived_parameter_name:
            base_name = re.sub(r'output_drain_._offset$', 'reset_drain', offset_name)
    return base_name

In [ ]:
def get_derived_parameter_name(name):
    if '_offset' not in name:
        return None
    offset_name = name
    return name.replace('_offset', '')

In [ ]:
data = {}

base_steps = 15

offset_steps = 5

set_fpe_defaults(fpe1)
for i in range(base_steps,0,-1):
    for j in range(offset_steps, 0, -1):
        for k in range(len(fpe1.ops.address)):
            # If there's no operating parameter to set, go on to the next one
            if fpe1.ops.address[k] is None:
                continue
            name = fpe1.ops.address[k].name
            base_name = get_base_name(name)
            derived_parameter_name = get_derived_parameter_name(name)
            # If there's no derived parameter reflecting this parameter, go on to the next one
            if derived_parameter_name is None:
                continue
            offset_name = name
            base_low = fpe1.ops[base_name].low
            base_high = fpe1.ops[base_name].high
            offset_low = fpe1.ops[offset_name].low
            offset_high = fpe1.ops[offset_name].high
            base_value = base_low + i / float(base_steps) * (base_high - base_low)
            fpe1.ops[base_name].value = base_value
            fpe1.ops[offset_name].value = offset_low + j / float(offset_steps) * (offset_high - offset_low)
        fpe1.ops.send()
        analogue_house_keeping = fpe1.house_keeping["analogue"]
        for k in range(len(fpe1.ops.address)):
            # If there's no operating parameter to set, go on to the next one
            if fpe1.ops.address[k] is None:
                continue
            name = fpe1.ops.address[k].name
            base_name = get_base_name(name)
            derived_parameter_name = get_derived_parameter_name(name)
            if derived_parameter_name is None:
                continue
            if derived_parameter_name not in data:
                data[derived_parameter_name] = {}
            offset_name = name
            base_low = fpe1.ops[base_name].low
            base_high = fpe1.ops[base_name].high
            offset_low = fpe1.ops[offset_name].low
            offset_high = fpe1.ops[offset_name].high
            base_value = base_low + i / float(base_steps) * (base_high - base_low)
            if base_value not in data[derived_parameter_name]:
                data[derived_parameter_name][base_value] = {"X": [], "Y": []}
            data[derived_parameter_name][base_value]["X"].append(fpe1.ops[base_name].value + 
                                                                 fpe1.ops[offset_name].value)
            data[derived_parameter_name][base_value]["Y"].append(analogue_house_keeping[derived_parameter_name])

Set up to plot:


In [ ]:
%matplotlib inline
%config InlineBackend.figure_format = 'svg'
import numpy as np
import matplotlib.pyplot as plt
import pylab

Plot selected data:


In [ ]:
def get_range_square(X,Y):
    return [min(X + Y)-1, max(X + Y)+1]

In [ ]:
# Plot the set vs. measured values of selected channels:
for nom in sorted(data.keys()):
    print nom
    for base_value in sorted(data[nom].keys()):
        print base_value
        X = data[nom][base_value]["X"]
        Y = data[nom][base_value]["Y"]
        ran = get_range_square(X,Y)
        pylab.ylim(ran)
        pylab.xlim(ran)
        pylab.grid(True)
        plt.axes().set_aspect(1)
        plt.title("{derived_param} with base {base}".format(
                derived_param=nom,
                base=base_value
            ))
        plt.scatter(X,Y,color='red')
        plt.plot(X,Y,color='blue')
        plt.show()

In [ ]: